%% Author: Administrator
%% Created: 2009-2-26
%% Description: TODO: Add description to data_importer
-module(data_importer).

%%
%% Include files
%%
-include("map.hrl").
-include("ring.hrl").

-include("data_util.hrl").

-define(SERVER, e2d_server).
-define(ZoomLevel, 15).


%%
%% Exported Functions
%%
-export([scan/1, collect/1]).
-export([get_files_dir/1]).

%%
%% API Functions
%%
scan(Level) ->
    case whereis(collector) of
        undefined ->
            ok;
        _Any ->
            collector ! {stop, 0}
    end,
    ListFile = get_files_dir(Level) ++ "list.txt",
    io:format("list File: ~s~n", [ListFile]),
    {ok, IoDevice} = file:open(ListFile, read),
    _HeadLine = io:get_line(IoDevice, ''),
    Pid = spawn(fun() -> collect({0,4000,0}) end),
    register(collector, Pid),
%    spectrometer_server:start("./priv/ext_spectrometer.o"),
    {Count} = each_line(IoDevice, io:get_line(IoDevice, ''), Level, {0}),
    file:close(IoDevice),
%    spectrometer_server:stop(),
    timer:sleep(1000),
    collector ! {stop, Count},
        
    ok.
    
%%
%% Local Functions
%%
get_files_dir(Level) ->
    ?ROOT ++ integer_to_list(Level) ++ "/".

each_line(_IoDevice, eof, _Level, {Count}) ->
%    SumTime = collect_loop(Spawned, 0),
    {Count};
each_line(IoDevice, Line, Level, {Count}) ->
    {FileName, CellId} = extract_id(Line, Level),
    spawn(fun() -> 
                Time = store_cell(CellId, FileName, Level), 
                collector ! {collect_time, Time}
          end)
    ,
    if 
        Count rem (10 * ?WRITER_POOL_SIZE) == 0 ->
            timer:sleep(1000),
            ok;
        true ->
            skip
    end,
    each_line(IoDevice, io:get_line(IoDevice, ''), Level, {Count+1}).

extract_id(Line, Level) ->
    [FileName | Rest] = string:tokens(Line, ": \n"),
    [Left, Right, Top, Bottom] = 
        lists:map(fun(Str) -> 
                      {Float, []} = string:to_float(Str), 
                      Float 
                  end, Rest),
    Longitude = (Left + Right) / 2,
    Latitude = (Top + Bottom) / 2,
    CellId = geo_util:get_quadtree_address(Longitude, Latitude, Level),
    {FileName, CellId}.


collect({AccTime, Min, Max}) ->
    receive
        {stop, 0} ->
            io:format("Count is ZERO??~n");
        {stop, Count} ->
            io:format("total_count=~p; each write, average time: ~p(ms), min=~p, max=~p, total_time=~p(ms)~n", [Count, AccTime/(1000*Count), Min/1000, Max/1000, AccTime/1000]);
        {collect_time, Time} ->
            NewMin = 
            if 
                Time < Min ->
                    Time;
                true ->
                    Min
            end,
            NewMax = 
            if    
                Time > Max ->
                    Time;
                true ->
                    Max
            end,
            collect({AccTime+Time, NewMin, NewMax})
    end.
    
store_cell(Id, FileName, Level) ->
%    log4erl:info("~s", [FileName]),
%    {ok, IoDevice} = file:open(get_files_dir(Level) ++ FileName, [raw, binary]),
    {ok, Data} = file:read_file(get_files_dir(Level) ++ FileName),

%     [{Xsize, Ysize, Bin1},{Xsize, Ysize, Bin2},{Xsize, Ysize, Bin3}] =
%         spectrometer_server:split_light(Data),
%     Band1 = new_img_band(red, Xsize, Ysize, Bin1),
%     Band2 = new_img_band(green, Xsize, Ysize, Bin2),
%     Band3 = new_img_band(blue, Xsize, Ysize, Bin3),
    
    Raster = #raster_tile{type="image/jpeg", data=Data},
    <<Key:128>> = crypto:md5(Id),
    CellValue = #cell{
                      id = Id, 
                      scale_factor = Level,
                      zone = geo_util:get_coordinates_from_address(Id), 
                      r_layer = Raster
%                      bands = [Band1, Band2, Band3]
                },
    put_to_ring(Key, CellValue).

put_to_ring(Key, Value) ->
%    gen_server:call(?SERVER, {api, {put, Key, Context, Value}}, infinity).
%    B = now(),
%    ring_accessor:put_to_ring(Key, Value),
%    Time = timer:now_diff(now(), B),
    {Time, Key} = timer:tc(ring_accessor, put_to_ring, [Key,Value]),
    Time.

new_img_band(Name, Xsize, Ysize, Bin) ->
    #img_band{
        name = Name,
        xsize = Xsize,
        ysize = Ysize,
        data = Bin
    }.